package com.sunwayworld.basemodule.common.eptstorage.file.excelread.service.impl;

import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.ExcelReader;
import com.alibaba.excel.read.builder.ExcelReaderBuilder;
import com.sunwayworld.basemodule.common.eptstorage.file.excelread.bean.LimsExcelReadconfigBean;
import com.sunwayworld.basemodule.common.eptstorage.file.excelread.bean.LimsSheetReadconfigBean;
import com.sunwayworld.basemodule.common.eptstorage.file.excelread.bean.LimsSheetTitleConfigBean;
import com.sunwayworld.basemodule.common.eptstorage.file.excelread.dao.LimsExcelReadconfigDao;
import com.sunwayworld.basemodule.common.eptstorage.file.excelread.listener.ExcelModelListener;
import com.sunwayworld.basemodule.common.eptstorage.file.excelread.listener.SheetData;
import com.sunwayworld.basemodule.common.eptstorage.file.excelread.service.IExcelDataStorageService;
import com.sunwayworld.basemodule.common.eptstorage.file.excelread.service.LimsExcelReadconfigService;
import com.sunwayworld.basemodule.common.eptstorage.file.excelread.service.LimsSheetReadconfigService;
import com.sunwayworld.basemodule.common.eptstorage.file.excelread.service.LimsSheetTitleConfigService;
import com.sunwayworld.cloud.lims.reporttemplate.support.util.LimsFileUtils;
import com.sunwayworld.framework.at.annotation.AuditTrailEntry;
import com.sunwayworld.framework.at.annotation.AuditTrailType;
import com.sunwayworld.framework.context.ApplicationContextHelper;
import com.sunwayworld.framework.exception.InvalidDataException;
import com.sunwayworld.framework.mybatis.mapper.MatchPattern;
import com.sunwayworld.framework.mybatis.mapper.SearchFilter;
import com.sunwayworld.framework.restful.data.RestJsonWrapperBean;
import com.sunwayworld.framework.spring.annotation.GikamBean;
import com.sunwayworld.framework.utils.ObjectUtils;
import com.sunwayworld.module.item.file.bean.CoreFileBean;
import com.sunwayworld.module.item.file.service.CoreFileService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;
import com.sunwayworld.baseline.framework.constant.StorageEngine;
import java.io.File;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Repository
@GikamBean
public class LimsExcelReadconfigServiceImpl implements LimsExcelReadconfigService {

    @Autowired
    private LimsExcelReadconfigDao limsExcelReadconfigDao;
    @Autowired
    private LimsSheetReadconfigService sheetReadconfigService;
    @Autowired
    private LimsSheetTitleConfigService titleConfigService;
    @Autowired
    private CoreFileService coreFileService;

    @Override
    @SuppressWarnings("unchecked")
    public LimsExcelReadconfigDao getDao() {
        return limsExcelReadconfigDao;
    }

    @Override
    @Transactional
    @AuditTrailEntry(AuditTrailType.INSERT)
    public Long insert(RestJsonWrapperBean jsonWrapper) {
        LimsExcelReadconfigBean limsExcelReadconfig = jsonWrapper.parseUnique(LimsExcelReadconfigBean.class);
        limsExcelReadconfig.setId(ApplicationContextHelper.getNextIdentity());
        getDao().insert(limsExcelReadconfig);
        return limsExcelReadconfig.getId();
    }

    @Override
    @Transactional
    public List<SheetData> testparse(RestJsonWrapperBean wrapper) {
        Map<String, String> paramMap = wrapper.getParamMap();
        LimsExcelReadconfigBean excelReadconfigBean = wrapper.parseUnique(LimsExcelReadconfigBean.class);

        List<LimsSheetReadconfigBean> sheetReadconfigBeans = sheetReadconfigService.selectListByFilter(SearchFilter.instance().match("excelid", excelReadconfigBean.getId()).filter(MatchPattern.SEQ));
        if(ObjectUtils.isEmpty(sheetReadconfigBeans)){
            throw new InvalidDataException("请维护sheet配置");
        }
        List<LimsSheetReadconfigBean> readconfigBeans = sheetReadconfigBeans.stream().filter(f -> "1".equals(f.getIfRead())).collect(Collectors.toList());
        if(ObjectUtils.isEmpty(readconfigBeans)){
            throw new InvalidDataException("没有要读取的sheet");
        }
        for (LimsSheetReadconfigBean readconfigBean : readconfigBeans) {
            String findSheetByName = readconfigBean.getFindSheetByName();
            if("1".equals(findSheetByName) && ObjectUtils.isEmpty(readconfigBean.getSheetName())){
                //按名称
                throw new InvalidDataException("按名称取sheet时，请配置sheet名称");
            }else if("0".equals(findSheetByName) && ObjectUtils.isEmpty(readconfigBean.getSheetNo())){
                throw new InvalidDataException("按序号取sheet时，请配置sheet序号");
            }
        }

        List<Long> sheetIds = readconfigBeans.stream().map(f->f.getId()).collect(Collectors.toList());
        List<LimsSheetTitleConfigBean> titleConfigBeans = titleConfigService.selectListByFilter(SearchFilter.instance().match("sheetId", sheetIds).filter(MatchPattern.OR));
        if(ObjectUtils.isEmpty(titleConfigBeans)){
            throw new InvalidDataException("请配置sheet下的字段列");
        }
        for (LimsSheetReadconfigBean readconfigBean : readconfigBeans) {
            List<LimsSheetTitleConfigBean> sheetTitleConfigBeans = titleConfigBeans.stream().filter(f -> f.getSheetId().longValue() == readconfigBean.getId().longValue()).collect(Collectors.toList());
            if(ObjectUtils.isEmpty(sheetTitleConfigBeans)){
                throw new InvalidDataException("请配置sheet【"+readconfigBean.getSheetName()+"】下的字段列");
            }
            for (LimsSheetTitleConfigBean sheetTitleConfigBean : sheetTitleConfigBeans) {
                if(ObjectUtils.isEmpty(sheetTitleConfigBean.getTitle())){
                    throw new InvalidDataException("请配置sheet【"+readconfigBean.getSheetName()+"】下的字段列名称");
                }
                if(ObjectUtils.isEmpty(sheetTitleConfigBean.getTitle_En())){
                    throw new InvalidDataException("请配置sheet【"+readconfigBean.getSheetName()+"】下的字段列英文名称");
                }
            }
        }

        String fileId = paramMap.get("fileId"); //要解析的excel 文件ID
        CoreFileBean coreFile = coreFileService.selectDetail(Long.parseLong(fileId));
        Path filePath = LimsFileUtils.getFilePath(coreFile);
        if(!filePath.toFile().exists()){
            throw new InvalidDataException(filePath+"is not found!");
        }

        List<SheetData> sheetDataList = parse(filePath.toFile(), readconfigBeans, titleConfigBeans);
        //测试数据不存入mongo,暂不注释方便测试
        //getExcelDataStorageService(excelReadconfigBean).storage(sheetDataList,null);

        return sheetDataList;
    }

    @Override
    public IExcelDataStorageService getExcelDataStorageService(LimsExcelReadconfigBean excelReadconfigBean){
        IExcelDataStorageService dataService = null;
        if(!ObjectUtils.isEmpty(excelReadconfigBean.getExcelDataStorageService())){
            dataService = ApplicationContextHelper.getBean(excelReadconfigBean.getExcelDataStorageService());
            if(dataService==null){
                throw new InvalidDataException("未实现Service【"+excelReadconfigBean.getExcelDataStorageService()+"】!");
            }
        }else{
            String storageEngine = excelReadconfigBean.getStorageEngine();
            if(ObjectUtils.isEmpty(storageEngine) || storageEngine.equals(StorageEngine.mongo.db)){
                dataService = ApplicationContextHelper.getBean(MongoExcelDataStorageService.class);
            }else if(storageEngine.equals(StorageEngine.clickhouse.db)){
                dataService = ApplicationContextHelper.getBean(ClickHouseExcelDataStorageService.class);
            }
        }
        return dataService;
    }

    @Override
    public List<SheetData> parse(File excelFile,List<LimsSheetReadconfigBean> readconfigBeans,List<LimsSheetTitleConfigBean> titleConfigBeans) {
        List<SheetData> sheetDatas = new ArrayList();
        ExcelReaderBuilder excelReaderBuilder = EasyExcel.read(excelFile, new ExcelModelListener(readconfigBeans,titleConfigBeans,sheetDatas));
        //excel读取配置
        //由于csv存在字符编码问题，这里从配置中取编码
        if(excelFile.getName().endsWith(".csv")){
            Long excelId = readconfigBeans.get(0).getExcelId();
            LimsExcelReadconfigBean excelReadconfigBean = this.selectById(excelId);
            excelReaderBuilder.customObject(excelReadconfigBean);
        }
//        excelReaderBuilder.readCache();
//        excelReaderBuilder.readCacheSelector()
        excelReaderBuilder.headRowNumber(0); //解析sheet时，返回从第一行开始的数据
        excelReaderBuilder.ignoreEmptyRow(false); //空行也读取
        ExcelReader excelReader = excelReaderBuilder.build();
        excelReader.readAll(); //具体解析的时候只解析指定的sheet
        excelReader.finish();
        return sheetDatas;
    }

}
